home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / Win_main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  28.8 KB  |  1,065 lines

  1. #include "stdafx.h"
  2. #include "qe3.h"
  3. #include <process.h>
  4. #include "mru.h"
  5. #include "entityw.h"
  6. #include "PrefsDlg.h"
  7.  
  8. static HWND      s_hwndToolbar;
  9.  
  10. BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize);
  11. BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize);
  12.  
  13. static HWND CreateMyStatusWindow(HINSTANCE hInst);
  14. static HWND CreateToolBar(HINSTANCE hinst);
  15.  
  16. extern void WXY_Print( void );
  17.  
  18. /*
  19. ==============================================================================
  20.  
  21.   MENU
  22.  
  23. ==============================================================================
  24. */
  25.  
  26. void OpenDialog (void);
  27. void SaveAsDialog (bool bRegion);
  28. qboolean ConfirmModified (void);
  29. void  Select_Ungroup (void);
  30.  
  31. void QE_ExpandBspString (char *bspaction, char *out, char *mapname, bool useTemps)
  32. {
  33.     char    *in;
  34.     char    src[2048];
  35.     char    rsh[2048];
  36.     char    base[2048];
  37.  
  38.     strcpy(src, mapname);
  39.     strlwr(src);
  40.     in = strstr(src, "maps/");
  41.     if (!in)
  42.     {
  43.         in = strstr(src, "maps\\");
  44.     }
  45.     if (in)
  46.     {
  47.         in += 5;
  48.         strcpy(base, in);
  49.         in = base;
  50.         while (*in)
  51.         {
  52.             if (*in == '\\')
  53.             {
  54.                 *in = '/';
  55.             }
  56.             in++;
  57.         }
  58.     }
  59.     else
  60.     {
  61.         ExtractFileName (mapname, base);
  62.     }
  63.  
  64.   if (useTemps) {
  65.     CString str;
  66.     CString strExt = "map";
  67.     if ( strstr(mapname, ".reg") ) {
  68.       strExt = "reg";
  69.     }
  70.     str.Format("%s/maps/%i.%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), ::GetTickCount(), strExt);
  71.     CopyFile(mapname, str, FALSE);
  72.       sprintf (src, "-tempname %s %s/maps/%s", str, ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
  73.   } else {
  74.       sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
  75.   }
  76.     strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd"));
  77.  
  78.   QE_ConvertDOSToUnixName(src, src);
  79.  
  80.     in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
  81.     while (*in)
  82.     {
  83.         if (in[0] == '!')
  84.         {
  85.             strcpy (out, rsh);
  86.             out += strlen(rsh);
  87.             in++;
  88.             continue;
  89.         }
  90.         if (in[0] == '$')
  91.         {
  92.             strcpy (out, src);
  93.             out += strlen(src);
  94.             in++;
  95.             continue;
  96.         }
  97.         if (in[0] == '@')
  98.         {
  99.             *out++ = '"';
  100.             in++;
  101.             continue;
  102.         }
  103.         *out++ = *in++;
  104.     }
  105.     *out = 0;
  106. }
  107.  
  108. void FindReplace(CString& strContents, const char* pTag, const char* pValue)
  109. {
  110.   if (strcmp(pTag, pValue) == 0)
  111.     return;
  112.   for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
  113.   {
  114.     int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
  115.     CString strLeft = strContents.Left(nPos);
  116.     CString strRight = strContents.Right(nRightLen);
  117.     strLeft += pValue;
  118.     strLeft += strRight;
  119.     strContents = strLeft;
  120.   }
  121. }
  122.  
  123.  
  124.  
  125. HWND g_hWnd = NULL;
  126. HANDLE g_hToolThread = NULL;
  127. CString g_strParams;
  128.  
  129. UINT ToolThread(LPVOID pParam)
  130. {
  131.   char* p = reinterpret_cast<char*>(pParam);
  132.   if (g_PrefsDlg.m_bPAK)
  133.     RunTools(p, g_hWnd, g_PrefsDlg.m_strPAKFile);
  134.   else
  135.     RunTools(p, g_hWnd, "");
  136.   g_hToolThread = NULL;
  137.   delete []p;
  138.   return 0;
  139. }
  140.  
  141. void ThreadTools(char* p)
  142. {
  143.   CWinThread* pThread = AfxBeginThread(ToolThread, reinterpret_cast<LPVOID>(p));
  144.   g_hToolThread = pThread->m_hThread;
  145. }
  146.  
  147. HWND g_hwndFoundIt = NULL;
  148.  
  149. BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
  150.   char buff[1024];
  151.   const char* p = reinterpret_cast<const char*>(lParam);
  152.   GetWindowText(hwnd, buff, 1024);
  153.   if (!strcmpi(p, buff)) {
  154.     g_hwndFoundIt = hwnd;
  155.     return 1;
  156.   }
  157.   return 1;
  158. }
  159.  
  160.  
  161. HWND FindAnyWindow(const char *pTitle) {
  162.   HWND hwndDesktop = GetDesktopWindow();
  163.   g_hwndFoundIt = NULL;
  164.   if ( hwndDesktop ) {
  165.     EnumChildWindows(hwndDesktop, (WNDENUMPROC)EnumChildProc, reinterpret_cast<LPARAM>(pTitle));
  166.   }
  167.   return g_hwndFoundIt;
  168. }
  169.  
  170.  
  171. const UINT wm_AddCommand = RegisterWindowMessage( "Q3MPC_AddCommand" );
  172.  
  173. CTime g_tBegin;
  174. void RunBsp (char *command)
  175. {
  176.     char    sys[2048];
  177.     char    batpath[2048];
  178.     char    outputpath[2048];
  179.     char    temppath[1024];
  180.     char    name[2048];
  181.     char    cWork[2048];
  182.     FILE    *hFile;
  183.     BOOL    ret;
  184.     PROCESS_INFORMATION ProcessInformation;
  185.     STARTUPINFO    startupinfo;
  186.   HWND hwndPClient = NULL;
  187.  
  188.   g_hWnd = g_pParentWnd->GetSafeHwnd();
  189.     SetInspectorMode(W_CONSOLE);
  190.   g_tBegin = CTime::GetCurrentTime();
  191.  
  192.     
  193.     DWORD    dwExitcode;
  194.   ret = GetExitCodeProcess (g_hToolThread, &dwExitcode);
  195.   if (dwExitcode != STILL_ACTIVE)
  196.     g_hToolThread = NULL;
  197.  
  198.     if (bsp_process || g_hToolThread)
  199.     {
  200.         Sys_Printf ("BSP is still going...\n");
  201.         return;
  202.     }
  203.  
  204.   outputpath[0] = '\0';
  205.     GetTempPath(512, temppath);
  206.  
  207.   CString strOutFile = temppath;
  208.   AddSlash(strOutFile);
  209.   strOutFile += "junk.txt";
  210.  
  211.     sprintf (outputpath, " >>%s\r\n", strOutFile);
  212.  
  213.   strcpy (name, currentmap);
  214.     if (region_active)
  215.     {
  216.         Map_SaveFile (name, false);
  217.         StripExtension (name);
  218.         strcat (name, ".reg");
  219.     }
  220.  
  221.     Map_SaveFile (name, region_active);
  222.  
  223.   // FIXME: this code just gets worse and worse
  224.   CString strPath, strFile;
  225.  
  226.   char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd");
  227.   if (rsh == NULL)
  228.   {
  229.     ExtractPath_and_Filename(name, strPath, strFile);
  230.     AddSlash(strPath);
  231.     BuildShortPathName(strPath, cWork, 1024);
  232.     strcat(cWork, strFile);
  233.   }
  234.   else
  235.   {
  236.     strcpy(cWork, name);
  237.   }
  238.  
  239.   hwndPClient = FindWindow(NULL, "Q3Map Process Client");
  240.   if ( hwndPClient == NULL ) {
  241.     hwndPClient = FindAnyWindow("Q3Map Process Client");
  242.   }
  243.  
  244.   Sys_Printf("Window info for Process Client %i\n", reinterpret_cast<int>(hwndPClient));
  245.  
  246.   bool processServer = (rsh && strlen(rsh) > 0 && hwndPClient);
  247.  
  248.   QE_ExpandBspString (command, sys, cWork, processServer);
  249.  
  250.   // if we can find the q3map process server running 
  251.   // we will submit maps to it instead of via createprocess
  252.   //
  253.   if (processServer)
  254.   {
  255.     CString str;
  256.     char cBuff[2048];
  257.     char *pStart = sys;
  258.     char *pEnd = strstr(pStart, "&&");
  259.     while (pEnd)
  260.     {
  261.       int nLen = pEnd-pStart-1;
  262.       strncpy(cBuff, pStart, nLen);
  263.       cBuff[nLen] = 0;
  264.       str = cBuff;
  265.       FindReplace(str, rsh, "");
  266.       str.TrimLeft(' ');
  267.       str.TrimRight(' ');
  268.       ATOM a = GlobalAddAtom(str);
  269.       PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
  270.       pStart = pEnd+2;
  271.       pEnd = strstr(pStart, "&&");
  272.     }
  273.     str = pStart;
  274.     FindReplace(str, rsh, "");
  275.     str.TrimLeft(' ');
  276.     str.TrimRight(' ');
  277.     ATOM a = GlobalAddAtom(str);
  278.     PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
  279.     Sys_Printf("Commands sent to Q3Map Process Client\n");
  280.     return;
  281.   }
  282.  
  283.   CString strSys = sys;
  284.  
  285.   FindReplace(strSys, "&&", outputpath);
  286.   strcpy(sys, strSys);
  287.   strcat(sys, outputpath);
  288.  
  289.   if (g_PrefsDlg.m_bInternalBSP)
  290.   {
  291.     g_tBegin = CTime::GetCurrentTime();
  292.     strSys.MakeLower();
  293.     char* p = new char[strSys.GetLength()+1];
  294.     strcpy(p, strSys.GetBuffer(0));
  295.     ThreadTools(p);
  296.   }
  297.   else
  298.   {
  299.       Sys_ClearPrintf ();
  300.       Sys_Printf ("==================\nRunning bsp command...\n");
  301.       Sys_Printf ("\n%s\n", sys);
  302.  
  303.       //++timo removed the old way BSP commands .. dumping to junk.txt doesn't work on my win98 box
  304.       // FIXME : will most likely break Quake2 BSP commands, is fitted to a one-lined sys command
  305.       //
  306.       // write qe3bsp.bat
  307.       //
  308.  
  309.       sprintf (batpath, "%sqe3bsp.bat", temppath);
  310.       hFile = fopen(batpath, "w");
  311.       if (!hFile)
  312.           Error ("Can't write to %s", batpath);
  313.       fprintf (hFile, sys);
  314.       fclose (hFile);
  315.  
  316.       Pointfile_Delete ();
  317.  
  318.       // delete junk.txt file
  319.       remove(strOutFile);
  320.  
  321.       GetStartupInfo (&startupinfo);
  322.  
  323.       ret = CreateProcess(
  324.           batpath,
  325.           NULL,
  326.           NULL,
  327.           NULL,
  328.           FALSE,
  329.           0,
  330.           NULL,
  331.           NULL,
  332.           &startupinfo,
  333.           &ProcessInformation
  334.           );
  335.  
  336.       if (!ret)
  337.           Error ("CreateProcess failed");
  338.  
  339.       bsp_process = ProcessInformation.hProcess;
  340.  
  341.       Sleep (100);    // give the new process a chance to open it's window
  342.  
  343.       BringWindowToTop( g_qeglobals.d_hwndMain );    // pop us back on top
  344. #if 0
  345.       //
  346.       // write qe3bsp.bat
  347.       //
  348.       sprintf (batpath, "%sqe3bsp.bat", temppath);
  349.       hFile = fopen(batpath, "w");
  350.       if (!hFile)
  351.           Error ("Can't write to %s", batpath);
  352.       fprintf (hFile, sys);
  353.       fclose (hFile);
  354.  
  355.       //
  356.       // write qe3bsp2.bat
  357.       //
  358.       sprintf (batpath, "%sqe3bsp2.bat", temppath);
  359.       hFile = fopen(batpath, "w");
  360.       if (!hFile)
  361.           Error ("Can't write to %s", batpath);
  362.       fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath);
  363.       fclose (hFile);
  364.  
  365.       Pointfile_Delete ();
  366.  
  367.       GetStartupInfo (&startupinfo);
  368.  
  369.       ret = CreateProcess(
  370.       batpath,        // pointer to name of executable module 
  371.       NULL,            // pointer to command line string
  372.       NULL,            // pointer to process security attributes 
  373.       NULL,            // pointer to thread security attributes 
  374.       FALSE,            // handle inheritance flag 
  375.       0 /*DETACHED_PROCESS*/,        // creation flags
  376.       NULL,            // pointer to new environment block 
  377.       NULL,            // pointer to current directory name 
  378.       &startupinfo,    // pointer to STARTUPINFO 
  379.       &ProcessInformation     // pointer to PROCESS_INFORMATION  
  380.      );
  381.  
  382.       if (!ret)
  383.           Error ("CreateProcess failed");
  384.  
  385.       bsp_process = ProcessInformation.hProcess;
  386.  
  387.       Sleep (100);    // give the new process a chance to open it's window
  388.  
  389.       //BringWindowToTop( g_qeglobals.d_hwndMain );    // pop us back on top
  390.       //SetFocus (g_qeglobals.d_hwndCamera);
  391. #endif
  392.   }
  393. }
  394.  
  395. void DLLBuildDone()
  396. {
  397.   g_hToolThread = NULL;
  398.   CTime tEnd = CTime::GetCurrentTime();
  399.   CTimeSpan tElapsed = tEnd - g_tBegin;
  400.   CString strElapsed;
  401.   strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds());
  402.     Sys_Printf(strElapsed.GetBuffer(0));
  403.     Pointfile_Check();
  404.  
  405.   if (g_PrefsDlg.m_bRunQuake == TRUE)
  406.   {
  407.     char cCurDir[1024];
  408.     GetCurrentDirectory(1024, cCurDir);
  409.     CString strExePath = g_PrefsDlg.m_strQuake2;
  410.     CString strOrgPath;
  411.     CString strOrgFile;
  412.     ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
  413.     if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map
  414.     {
  415.         CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
  416.       strExePath += " +set game ";
  417.       strExePath += strBasePath;
  418.       WinExec(strExePath, SW_SHOW);
  419.     }
  420.     else
  421.     {
  422.       CString strCopyPath = strExePath;
  423.       char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1);
  424.       pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0';
  425.       strCopyPath.ReleaseBuffer();
  426.       SetCurrentDirectory(strCopyPath);
  427.       CString strOrgPath;
  428.       CString strOrgFile;
  429.       ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
  430.       AddSlash(strCopyPath);
  431.       FindReplace(strOrgFile, ".map", ".bsp");
  432.       strCopyPath += "\\baseq2\\maps\\";
  433.       strCopyPath += strOrgFile;
  434.       AddSlash(strOrgPath);
  435.       strOrgPath += strOrgFile;
  436.       bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0);
  437.       if (!bRun)
  438.         bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE);
  439.       if (bRun)
  440.       {
  441.         FindReplace(strOrgFile, ".bsp", "");
  442.         strExePath += " +map ";
  443.         strExePath += strOrgFile;
  444.         WinExec(strExePath, SW_SHOW);
  445.       }
  446.     }
  447.     SetCurrentDirectory(cCurDir);
  448.   }
  449.  
  450. }
  451.  
  452. /*
  453. =============
  454. DoColor
  455.  
  456. =============
  457. */
  458.  
  459. class CMyColorDialog : public CColorDialog 
  460. {
  461.   DECLARE_DYNCREATE(CMyColorDialog);
  462.      // Construction
  463. public:
  464.      CMyColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd*
  465. pParentWnd = NULL );
  466.      // Statics
  467. protected:
  468.      enum { NCUSTCOLORS = 16 };
  469.      static COLORREF c_CustColors[NCUSTCOLORS];
  470.      static COLORREF c_LastCustColors[NCUSTCOLORS];
  471.      static bool c_NeedToInitCustColors;
  472. protected:
  473.      static void InitCustColors();
  474.      static void SaveCustColors();
  475.      // Dialog Data
  476. protected:
  477.      //{{AFX_DATA(CMyColorDialog)
  478.      //}}AFX_DATA
  479.      // Overrides
  480. protected:
  481.      // ClassWizard generate virtual function overrides
  482.      //{{AFX_VIRTUAL(CMyColorDialog)
  483. public:
  484.      virtual int DoModal();
  485. protected:
  486.      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  487.      //}}AFX_VIRTUAL
  488.      // Implementation
  489. protected:
  490.      // Generated message map functions
  491.      //{{AFX_MSG(CMyColorDialog)
  492.      //}}AFX_MSG
  493.      DECLARE_MESSAGE_MAP()
  494. };
  495.  
  496. IMPLEMENT_DYNCREATE(CMyColorDialog, CColorDialog)
  497.  
  498. bool CMyColorDialog::c_NeedToInitCustColors = true;
  499. COLORREF CMyColorDialog::c_CustColors[];
  500. COLORREF CMyColorDialog::c_LastCustColors[];
  501.  
  502. #define SECTION _T("Custom Colors")
  503.  
  504. void CMyColorDialog::InitCustColors() {
  505.      for (int i = 0; i < NCUSTCOLORS; i++) {
  506.           CString entry; entry.Format("%d",i);
  507.           c_LastCustColors[i] = c_CustColors[i] =
  508.         ::AfxGetApp()->GetProfileInt(SECTION,entry,RGB(255,255,255));
  509.      }
  510.      c_NeedToInitCustColors= false;
  511. }
  512.  
  513. void CMyColorDialog::SaveCustColors() {
  514.      for (int i = 0; i < NCUSTCOLORS; i++) {
  515.           if (c_LastCustColors[i] != c_CustColors[i]) {
  516.                CString entry; entry.Format("%d",i);
  517.                if (c_CustColors[i] == RGB(255,255,255)) {
  518.                     ::AfxGetApp()->WriteProfileString(SECTION,entry,NULL);
  519.                } else {
  520.                     ::AfxGetApp()->WriteProfileInt(SECTION, entry,c_CustColors[i]);
  521.                }
  522.                c_LastCustColors[i] = c_CustColors[i];
  523.           }
  524.      }
  525. }
  526.  
  527. CMyColorDialog::CMyColorDialog( COLORREF clrInit, DWORD dwFlags, 
  528.         CWnd* pParentWnd) : CColorDialog(clrInit,dwFlags,pParentWnd)
  529. {
  530.      //{{AFX_DATA_INIT(CMyColorDialog)
  531.      //}}AFX_DATA_INIT
  532.      if (c_NeedToInitCustColors) {
  533.           InitCustColors();
  534.      }
  535.      m_cc.lpCustColors = c_CustColors;
  536. }
  537.  
  538. int CMyColorDialog::DoModal() {
  539.      int code = CColorDialog::DoModal();
  540.      SaveCustColors();
  541.      return code;
  542. }
  543.  
  544. void CMyColorDialog::DoDataExchange(CDataExchange* pDX) {
  545.      // overridden (calls this base class)
  546.      CColorDialog::DoDataExchange(pDX);
  547.      //{{AFX_DATA_MAP(CMyColorDialog)
  548.      //}}AFX_DATA_MAP
  549. }
  550.  
  551. BEGIN_MESSAGE_MAP(CMyColorDialog, CColorDialog)
  552. //{{AFX_MSG_MAP(CMyColorDialog)
  553. //}}AFX_MSG_MAP
  554. END_MESSAGE_MAP()
  555.  
  556. void DoNewColor(int* i1, int* i2, int* i3)
  557. {
  558.     COLORREF cr = (*i1) +
  559.                 ((*i2) <<8) +
  560.                     ((*i3) <<16);
  561.   CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
  562.   if (dlg.DoModal() == IDOK)
  563.   {
  564.       *i1 = (dlg.m_cc.rgbResult & 255);
  565.       *i2 = ((dlg.m_cc.rgbResult >> 8) & 255);
  566.       *i3 = ((dlg.m_cc.rgbResult >> 16) & 255);
  567.   }
  568.  
  569. }
  570.  
  571.  
  572. qboolean DoColor(int iIndex)
  573. {
  574.  
  575.     COLORREF cr = (int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) +
  576.                 (((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) +
  577.                     (((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16);
  578.   CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
  579.   if (dlg.DoModal() == IDOK)
  580.   {
  581.       g_qeglobals.d_savedinfo.colors[iIndex][0] = (dlg.m_cc.rgbResult&255)/255.0;
  582.       g_qeglobals.d_savedinfo.colors[iIndex][1] = ((dlg.m_cc.rgbResult>>8)&255)/255.0;
  583.       g_qeglobals.d_savedinfo.colors[iIndex][2] = ((dlg.m_cc.rgbResult>>16)&255)/255.0;
  584.  
  585.       /* 
  586.       ** scale colors so that at least one component is at 1.0F 
  587.       ** if this is meant to select an entity color
  588.       */
  589.       if ( iIndex == COLOR_ENTITY )
  590.       {
  591.           float largest = 0.0F;
  592.  
  593.           if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest )
  594.               largest = g_qeglobals.d_savedinfo.colors[iIndex][0];
  595.           if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest )
  596.               largest = g_qeglobals.d_savedinfo.colors[iIndex][1];
  597.           if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest )
  598.               largest = g_qeglobals.d_savedinfo.colors[iIndex][2];
  599.  
  600.           if ( largest == 0.0F )
  601.           {
  602.               g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F;
  603.               g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F;
  604.               g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F;
  605.           }
  606.           else
  607.           {
  608.               float scaler = 1.0F / largest;
  609.  
  610.               g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler;
  611.               g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler;
  612.               g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler;
  613.           }
  614.       }
  615.  
  616.       Sys_UpdateWindows (W_ALL);
  617.       return true;
  618.   }
  619.   else return false;
  620.  
  621. }
  622.  
  623.  
  624. /* Copied from MSDN */
  625.  
  626. BOOL DoMru(HWND hWnd,WORD wId)
  627. {
  628.     char szFileName[128];
  629.     OFSTRUCT of;
  630.     BOOL fExist;
  631.  
  632.     GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName));
  633.  
  634.     // Test if the file exists.
  635.  
  636.     fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR;
  637.  
  638.     if (fExist) {
  639.  
  640.         // Place the file on the top of MRU.
  641.         AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName);
  642.  
  643.         // Now perform opening this file !!!
  644.         Map_LoadFile (szFileName);    
  645.     }
  646.     else
  647.         // Remove the file on MRU.
  648.         DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE);
  649.  
  650.     // Refresh the File menu.
  651.     PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0),
  652.             ID_FILE_EXIT);
  653.  
  654.     return fExist;
  655. }
  656.  
  657.  
  658.  
  659. /*
  660. ==============
  661. Main_Create
  662. ==============
  663. */
  664.  
  665. void MFCCreate (HINSTANCE hInstance)
  666. {
  667.     HMENU hMenu = NULL;
  668.     int i = sizeof(g_qeglobals.d_savedinfo);
  669.   long l = i;
  670.  
  671.   g_qeglobals.d_savedinfo.exclude |= (EXCLUDE_HINT | EXCLUDE_CLIP);
  672.     LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
  673.  
  674.   int nOldSize = g_qeglobals.d_savedinfo.iSize;
  675.     if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo))
  676.     {
  677.         // fill in new defaults
  678.         g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo);
  679.         g_qeglobals.d_savedinfo.fGamma = 1.0;
  680.         g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_BILINEARMIPMAP;
  681.     g_qeglobals.d_savedinfo.m_nTextureTweak = 1;
  682.   
  683.         //g_qeglobals.d_savedinfo.exclude = INCLUDE_EASY | INCLUDE_NORMAL | INCLUDE_HARD | INCLUDE_DEATHMATCH;
  684.         g_qeglobals.d_savedinfo.show_coordinates = true;
  685.         g_qeglobals.d_savedinfo.show_names       = false;
  686.  
  687.         for (i=0 ; i<3 ; i++)
  688.         {
  689.             g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
  690.             g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
  691.             g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75;
  692.             g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
  693.             g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
  694.         }
  695.  
  696.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
  697.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
  698.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
  699.  
  700.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0;
  701.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0;
  702.         g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0;
  703.  
  704.         g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
  705.         g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
  706.         g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
  707.  
  708.         g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
  709.         g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
  710.         g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
  711.  
  712.         g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0;
  713.         g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0;
  714.         g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0;
  715.  
  716.         g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5;
  717.         g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0;
  718.         g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75;
  719.  
  720.  
  721.     // old size was smaller, reload original prefs
  722.     if (nOldSize < sizeof(g_qeglobals.d_savedinfo))
  723.     {
  724.       long l = nOldSize;
  725.         LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
  726.     }
  727.  
  728.     }
  729.     if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 )
  730.     {
  731.         // by default all of these are checked because that's how they're defined in the menu editor
  732.         if ( !g_qeglobals.d_savedinfo.show_names )
  733.             CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED );
  734.         if ( !g_qeglobals.d_savedinfo.show_coordinates )
  735.             CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED );
  736.  
  737.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS )
  738.             CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
  739.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT )
  740.             CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED );
  741.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS )
  742.             CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
  743.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER )
  744.             CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
  745.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD )
  746.             CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
  747.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP )
  748.             CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
  749.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT )
  750.             CheckMenuItem( hMenu, ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED );
  751.         if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK )
  752.             CheckMenuItem( hMenu, ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED );
  753.     }
  754.  
  755. }
  756.  
  757.  
  758. /*
  759. =============================================================
  760.  
  761. REGISTRY INFO
  762.  
  763. =============================================================
  764. */
  765.  
  766. BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize)
  767. {
  768.     LONG lres;
  769.     DWORD dwDisp;
  770.     HKEY  hKeyId;
  771.  
  772.     if (g_qeglobals.use_ini)
  773.     {
  774.         lres = RegCreateKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, NULL,
  775.             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
  776.     }
  777.     else
  778.     {
  779.         lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, NULL, 
  780.                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
  781.     }
  782.     
  783.     if (lres != ERROR_SUCCESS)
  784.         return FALSE;
  785.  
  786.     lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, (unsigned char*)pvBuf, lSize);
  787.     
  788.     RegCloseKey(hKeyId);
  789.  
  790.     if (lres != ERROR_SUCCESS)
  791.         return FALSE;
  792.  
  793.     return TRUE;
  794. }
  795.  
  796. BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize)
  797. {
  798.     HKEY  hKey;
  799.     long lres, lType, lSize;
  800.  
  801.     if (plSize == NULL)
  802.         plSize = &lSize;
  803.  
  804.     if (g_qeglobals.use_ini)
  805.     {
  806.         lres = RegOpenKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, KEY_READ, &hKey);
  807.     }
  808.     else
  809.     {
  810.         lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, KEY_READ, &hKey);
  811.   }
  812.  
  813.     lres = RegQueryValueEx(hKey, pszName, NULL, (unsigned long*)&lType, (unsigned char*)pvBuf, (unsigned long*)plSize);
  814.  
  815.     RegCloseKey(hKey);
  816.  
  817.     if (lres != ERROR_SUCCESS)
  818.     {
  819. #ifdef _DEBUG
  820.         char Message[1024];
  821.         FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, lres, 0, &(Message[0]), 1024, NULL );
  822.         Sys_Printf( "WARNING: RegQueryValueEx failed in LoadRegistryInfo for %s : %s", pszName, Message );
  823. #endif
  824.         return FALSE;
  825.     }
  826.  
  827.     return TRUE;
  828. }
  829.  
  830. BOOL SaveWindowState(HWND hWnd, const char *pszName)
  831. {
  832.     RECT rc;
  833.     GetWindowRect(hWnd, &rc);
  834.     if (hWnd != g_qeglobals.d_hwndMain) // && g_pParentWnd->CurrentStyle() == QR_QE4)
  835.   {
  836.     if (::GetParent(hWnd) != g_qeglobals.d_hwndMain)
  837.     {
  838.       ::SetParent(hWnd, g_qeglobals.d_hwndMain);
  839.     }
  840.         MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2);
  841.  
  842.   }
  843.     BOOL b = SaveRegistryInfo(pszName, &rc, sizeof(rc));
  844.   return b;
  845. }
  846.  
  847.  
  848. BOOL LoadWindowState(HWND hWnd, const char *pszName)
  849. {
  850.     RECT rc;
  851.   LONG lSize = sizeof(rc);
  852.  
  853.     if (LoadRegistryInfo(pszName, &rc, &lSize))
  854.     {
  855.         if (rc.left < 0)
  856.             rc.left = 0;
  857.         if (rc.top < 0)
  858.             rc.top = 0;
  859.         if (rc.right < rc.left + 16)
  860.             rc.right = rc.left + 16;
  861.         if (rc.bottom < rc.top + 16)
  862.             rc.bottom = rc.top + 16;
  863.  
  864.         MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left, 
  865.                 rc.bottom - rc.top, FALSE);
  866.         return TRUE;
  867.     }
  868.  
  869.     return FALSE;
  870. }
  871.  
  872. /*
  873. ===============================================================
  874.  
  875.   STATUS WINDOW
  876.  
  877. ===============================================================
  878. */
  879.  
  880. void Sys_UpdateStatusBar( void )
  881. {
  882.     extern int   g_numbrushes, g_numentities;
  883.  
  884.     char numbrushbuffer[100]="";
  885.  
  886.     sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
  887.   g_pParentWnd->SetStatusText(2, numbrushbuffer);
  888.     //Sys_Status( numbrushbuffer, 2 );
  889. }
  890.  
  891. void Sys_Status(const char *psz, int part )
  892. {
  893.     SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz);
  894. }
  895.  
  896. static HWND CreateMyStatusWindow(HINSTANCE hInst)
  897. {
  898.     HWND hWnd;
  899.     int partsize[3] = { 300, 1100, -1 };
  900.  
  901.     hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles
  902.             STATUSCLASSNAME,                 // status bar
  903.             "",                              // no text 
  904.             WS_CHILD | WS_BORDER | WS_VISIBLE,  // styles
  905.             -100, -100, 10, 10,              // x, y, cx, cy
  906.             g_qeglobals.d_hwndMain,          // parent window
  907.             (HMENU)100,                      // window ID
  908.             hInst,                           // instance
  909.             NULL);                             // window data
  910.  
  911.     SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize );
  912.     
  913.     return hWnd;
  914. }
  915.  
  916. //==============================================================
  917.  
  918. #define NUMBUTTONS 15
  919. HWND CreateToolBar(HINSTANCE hinst)
  920.     HWND hwndTB; 
  921.     TBADDBITMAP tbab; 
  922.     TBBUTTON tbb[NUMBUTTONS]; 
  923.     
  924.      // Ensure that the common control DLL is loaded. 
  925.  
  926.     InitCommonControls(); 
  927.  
  928.     // Create a toolbar that the user can customize and that has a 
  929.     // tooltip associated with it. 
  930.  
  931.     hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL, 
  932.         WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER, 
  933.         0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL); 
  934.  
  935.     // Send the TB_BUTTONSTRUCTSIZE message, which is required for 
  936.     // backward compatibility. 
  937.  
  938.     SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
  939.  
  940.     // Add the bitmap containing button images to the toolbar. 
  941.  
  942.     tbab.hInst = hinst; 
  943.     tbab.nID   = IDR_TOOLBAR1; 
  944.     SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab); 
  945.  
  946.     // Fill the TBBUTTON array with button information, and add the 
  947.     // buttons to the toolbar. 
  948.  
  949.     tbb[0].iBitmap = 0; 
  950.     tbb[0].idCommand = ID_BRUSH_FLIPX; 
  951.     tbb[0].fsState = TBSTATE_ENABLED; 
  952.     tbb[0].fsStyle = TBSTYLE_BUTTON; 
  953.     tbb[0].dwData = 0; 
  954.     tbb[0].iString = 0; 
  955.  
  956.     tbb[1].iBitmap = 2; 
  957.     tbb[1].idCommand = ID_BRUSH_FLIPY; 
  958.     tbb[1].fsState = TBSTATE_ENABLED; 
  959.     tbb[1].fsStyle = TBSTYLE_BUTTON; 
  960.     tbb[1].dwData = 0; 
  961.     tbb[1].iString = 0; 
  962.  
  963.     tbb[2].iBitmap = 4; 
  964.     tbb[2].idCommand = ID_BRUSH_FLIPZ; 
  965.     tbb[2].fsState = TBSTATE_ENABLED;
  966.     tbb[2].fsStyle = TBSTYLE_BUTTON; 
  967.     tbb[2].dwData = 0; 
  968.     tbb[2].iString = 0; 
  969.  
  970.     tbb[3].iBitmap = 1; 
  971.     tbb[3].idCommand = ID_BRUSH_ROTATEX; 
  972.     tbb[3].fsState = TBSTATE_ENABLED; 
  973.     tbb[3].fsStyle = TBSTYLE_BUTTON; 
  974.     tbb[3].dwData = 0; 
  975.     tbb[3].iString = 0; 
  976.  
  977.     tbb[4].iBitmap = 3; 
  978.     tbb[4].idCommand = ID_BRUSH_ROTATEY; 
  979.     tbb[4].fsState = TBSTATE_ENABLED; 
  980.     tbb[4].fsStyle = TBSTYLE_BUTTON; 
  981.     tbb[4].dwData = 0; 
  982.     tbb[4].iString = 0; 
  983.  
  984.     tbb[5].iBitmap = 5; 
  985.     tbb[5].idCommand = ID_BRUSH_ROTATEZ; 
  986.     tbb[5].fsState = TBSTATE_ENABLED; 
  987.     tbb[5].fsStyle = TBSTYLE_BUTTON; 
  988.     tbb[5].dwData = 0; 
  989.     tbb[5].iString = 0; 
  990.  
  991.     tbb[6].iBitmap = 6; 
  992.     tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL; 
  993.     tbb[6].fsState = TBSTATE_ENABLED; 
  994.     tbb[6].fsStyle = TBSTYLE_BUTTON; 
  995.     tbb[6].dwData = 0; 
  996.     tbb[6].iString = 0; 
  997.  
  998.     tbb[7].iBitmap = 7; 
  999.     tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING; 
  1000.     tbb[7].fsState = TBSTATE_ENABLED; 
  1001.     tbb[7].fsStyle = TBSTYLE_BUTTON; 
  1002.     tbb[7].dwData = 0; 
  1003.     tbb[7].iString = 0; 
  1004.  
  1005.     tbb[8].iBitmap = 8; 
  1006.     tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL; 
  1007.     tbb[8].fsState = TBSTATE_ENABLED; 
  1008.     tbb[8].fsStyle = TBSTYLE_BUTTON; 
  1009.     tbb[8].dwData = 0; 
  1010.     tbb[8].iString = 0; 
  1011.  
  1012.  
  1013.     tbb[9].iBitmap = 9; 
  1014.     tbb[9].idCommand = ID_SELECTION_SELECTINSIDE; 
  1015.     tbb[9].fsState = TBSTATE_ENABLED; 
  1016.     tbb[9].fsStyle = TBSTYLE_BUTTON; 
  1017.     tbb[9].dwData = 0; 
  1018.     tbb[9].iString = 0; 
  1019.  
  1020.     tbb[10].iBitmap = 10; 
  1021.     tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT; 
  1022.     tbb[10].fsState = TBSTATE_ENABLED; 
  1023.     tbb[10].fsStyle = TBSTYLE_BUTTON; 
  1024.     tbb[10].dwData = 0; 
  1025.     tbb[10].iString = 0; 
  1026.  
  1027.  
  1028.     tbb[11].iBitmap = 11;
  1029.     tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW; 
  1030.     tbb[11].fsState = TBSTATE_ENABLED; 
  1031.     tbb[11].fsStyle = TBSTYLE_BUTTON; 
  1032.     tbb[11].dwData = 0; 
  1033.     tbb[11].iString = 0; 
  1034.  
  1035.     tbb[12].iBitmap = 12;
  1036.     tbb[12].idCommand = ID_TEXTURES_WIREFRAME; 
  1037.     tbb[12].fsState = TBSTATE_ENABLED; 
  1038.     tbb[12].fsStyle = TBSTYLE_BUTTON; 
  1039.     tbb[12].dwData = 0; 
  1040.     tbb[12].iString = 0; 
  1041.  
  1042.     tbb[13].iBitmap = 13;
  1043.     tbb[13].idCommand = ID_TEXTURES_FLATSHADE; 
  1044.     tbb[13].fsState = TBSTATE_ENABLED; 
  1045.     tbb[13].fsStyle = TBSTYLE_BUTTON; 
  1046.     tbb[13].dwData = 0; 
  1047.     tbb[13].iString = 0; 
  1048.  
  1049.     tbb[14].iBitmap = 14;
  1050.     tbb[14].idCommand = ID_VIEW_TRILINEAR; 
  1051.     tbb[14].fsState = TBSTATE_ENABLED; 
  1052.     tbb[14].fsStyle = TBSTYLE_BUTTON; 
  1053.     tbb[14].dwData = 0; 
  1054.     tbb[14].iString = 0; 
  1055.  
  1056.     SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS,
  1057.         (LPARAM) (LPTBBUTTON) &tbb); 
  1058.  
  1059.     ShowWindow(hwndTB, SW_SHOW); 
  1060.  
  1061.     return hwndTB; 
  1062.  
  1063.